package com.mgq.juc.cas;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 对原子数组的使用
 *
 * 保护的数组里面的元素线程安全
 */
public class TestAtomicArray {


    public static void main(String[] args) {
        //线程不安全的数组
        demo(
                () -> new int[10],
                (array)->array.length,
                (array,index)->array[index]++,
                (array)-> System.out.println(Arrays.toString(array))
        );
        //线程安全的原子数组
        demo(
                ()->new AtomicIntegerArray(10),
                AtomicIntegerArray::length,
                AtomicIntegerArray::getAndIncrement,
                System.out::println

        );
    }

    /**
     *
     * @param supplier 提供一个数组,可以是一个安全的数组,也可以是一个不安全的数组 supplier:无中生有
     * @param function 获取数组的长度                                     function:一个参数,一个结果 biFunction 2个参数,一个结果
     * @param biConsumer 自增方法 回传array,index                         consumer:消费结果 一个参数,无结果 biConsumer
     * @param consumer 打印数组的方法
     * @param <T>
     */
    public static <T> void demo(
            Supplier<T> supplier,
            Function<T, Integer> function,
            BiConsumer<T,Integer> biConsumer,
            Consumer<T> consumer
            ) {
        List<Thread> list = new ArrayList<>();
        T array = supplier.get();
        //返回数组的长度
        Integer length = function.apply(array);
        //
        for (int i = 0; i < length; i++) {
            Thread thread = new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    //提供 array,index
                    biConsumer.accept(array, j % length);
                }

            });
            thread.start();
            list.add(thread);
        }
        //等待所有线程执行结束
        list.forEach((thread)->{
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        consumer.accept(array);
    }
}
